package glemipsc.implementations;

import glemipsc.AbsoluteAddress;
import glemipsc.Address;
import glemipsc.GLEMipsEmu;

import java.util.ArrayList;
import java.util.Iterator;

public abstract class Instruction {

	public static final String NOP = "000000";
	public static final String ADDU = "000010";
	public static final String ADDS = "000001";
	public static final String SUBU = "000100";
	public static final String SUBS = "000011";
	public static final String MULU = "000110";
	public static final String MULS = "000101";
	public static final String DIVU = "001000";
	public static final String DIVS = "000111";
	public static final String AND = "001001";
	public static final String OR = "001010";
	public static final String XOR = "001011";
	public static final String LD32 = "001101";
	public static final String LD16 = "001110";
	public static final String LD8 = "001111";
	public static final String ST32 = "010000";
	public static final String ST16 = "010001";
	public static final String ST8 = "010010";
	public static final String JMP = "010011";
	public static final String JAL = "010100";
	public static final String JZ = "011101";
	public static final String JNZ = "011110";
	public static final String JLZ = "011111";
	public static final String JGZ = "100000";
	public static final String JLEZ = "100001";
	public static final String JGEZ = "100010";
	public static final String LLS = "001000";
	public static final String LRS = "001001";
	public static final String ALS = "001010";
	public static final String ARS = "001011";
	public static final String LR = "001100";
	public static final String RR = "001101";
	public static final String MOV = "100011";
	public static final String ALU = "001100";
	public static final String ALU_ADDS = "000001";
	public static final String ALU_ADDU = "000010";
	public static final String ALU_SUBS = "000011";
	public static final String ALU_SUBU = "000100";
	public static final String ALU_MULS = "000101";
	public static final String ALU_MULU = "000110";
	public static final String ALU_DIVS = "000111";
	public static final String ALU_DIVU = "001000";
	public static final String ALU_MOV = "010010";
	public static final String ALU_LLS = "001000";
	public static final String ALU_LRS = "001001";
	public static final String ALU_ALS = "001010";
	public static final String ALU_ARS = "001011";
	public static final String ALU_LR = "001100";
	public static final String ALU_RR = "001101";
	public static final String ALU_AND = "001110";
	public static final String ALU_OR = "001111";
	public static final String ALU_XOR = "010000";

	protected ArrayList<Argument> arguments = new ArrayList<Argument>();
	protected Address address = new AbsoluteAddress(0);
	
	protected String zeros(int n) {
		String tmp = "";
		
		for (int i = 0; i < n; i++)
			tmp += "0";
		return tmp;
	}
	
	public void addArgument(Argument argument) {
		arguments.add(argument);
	}
	
	public int getSize() {
		return 4;
	}
	
	public String getAsmCode() {
		String code = getName();
		Iterator<Argument> iter = arguments.iterator();
		while (iter.hasNext()) {
			Argument next = iter.next();
			if (next instanceof Address)
				code += " " + ((Address) next).getOffset().toString();
			else
				code += " " + next.toString();
			if (iter.hasNext())
				code += ",";
		}
		return code + ";\n";
	}
	
	public void setAddress(int addr) {
		address.setValue(addr);
	}
	
	public Address getAddress() {
		return address;
	}
	
	public boolean isNop() {
		return false;
	}
	
	public abstract String getOpCode();
	public abstract String getName();
	
	public abstract void emulate(GLEMipsEmu emu);
}